package net.logax.games.chase.map;

import java.util.ArrayList;

import net.logax.games.chase.map.Map.MapFragment;

public class CandidateFinderByPreviousNX implements CandidateFinder {

	private Map.MapFragment fragNX;
	private Map.MapFragment fragX;
	private Map.MapFragment fragNY;
	private Map.MapFragment fragY;
	private Map.MapFragment fragNXY;
	private Map.MapFragment fragXY;
	private Map.MapFragment fragNXNY;
	private Map.MapFragment fragXNY;

	final private int creationIndexX;
	final private int creationIndexY;
	final private int creationIndexZ;

	public CandidateFinderByPreviousNX(Map.MapFragment[][][] mapArray, int[] currentCoordinate) {
		creationIndexX = currentCoordinate[0];
		creationIndexY = currentCoordinate[1];
		creationIndexZ = currentCoordinate[2];
		fragNX = mapArray[creationIndexX - 1][creationIndexY][creationIndexZ];
		fragX = mapArray[creationIndexX + 1][creationIndexY][creationIndexZ];
		fragNY = mapArray[creationIndexX][creationIndexY - 1][creationIndexZ];
		fragY = mapArray[creationIndexX][creationIndexY + 1][creationIndexZ];
		fragNXY = mapArray[creationIndexX - 1][creationIndexY + 1][creationIndexZ];
		fragXY = mapArray[creationIndexX + 1][creationIndexY + 1][creationIndexZ];
		fragNXNY = mapArray[creationIndexX - 1][creationIndexY - 1][creationIndexZ];
		fragXNY = mapArray[creationIndexX + 1][creationIndexY - 1][creationIndexZ];
	}

	/**
	 * Erstellungsmarker war zuvor bei NX
	 */
	public ArrayList<Map.MapFragment> findCandidates(int corridorLength, int corridorSegmentCount) throws Exception {
		if (MapBuilder.DEBUG) {
			MapDebugUtils.printSurrounding(this, fragNX, fragX, fragNY, fragY, fragNXY, fragXY, fragNXNY, fragXNY);
		}
		ArrayList<Map.MapFragment> possibilities = new ArrayList<Map.MapFragment>();
		if (fragNX.equals(Map.MapFragment.CORRIDOR_X)) {

			checkDirectionX(corridorLength, possibilities, corridorSegmentCount);
			checkDirectionY(corridorLength, corridorSegmentCount, possibilities);
			checkDirectionNY(corridorLength, corridorSegmentCount, possibilities);
			checkDirectionsYNY(corridorLength, corridorSegmentCount, possibilities);
		} else if (fragNX.equals(Map.MapFragment.CURVE_X_NY) || (fragNX.equals(Map.MapFragment.T_CROSSING_NY))) {
			checkDirectionX(corridorLength, possibilities, corridorSegmentCount);
			checkDirectionY(corridorLength, corridorSegmentCount, possibilities);
		} else if (fragNX.equals(Map.MapFragment.CURVE_X_Y) || (fragNX.equals(Map.MapFragment.T_CROSSING_Y))) {
			checkDirectionX(corridorLength, possibilities, corridorSegmentCount);
			checkDirectionNY(corridorLength, corridorSegmentCount, possibilities);
		} else if (fragNX.equals(Map.MapFragment.CROSSING) || (fragNX.equals(Map.MapFragment.T_CROSSING_X))) {
			checkDirectionX(corridorLength, possibilities, corridorSegmentCount);
		} else {
			MapDebugUtils.printSurrounding(this, fragNX, fragX, fragNY, fragY, fragNXY, fragXY, fragNXNY, fragXNY);
			throw new Exception("previous was NX, could not find a candidate");
		}
		if (MapBuilder.DEBUG) {
			System.out.println("Possibilities" + possibilities.toString());
		}
		return possibilities;
	}

	private void checkDirectionX(int corridorLength, ArrayList<Map.MapFragment> possibilities, int corridorSegmentCount) {
		if (fragX.equals(MapFragment.EMPTY)) {
			if (corridorSegmentCount < corridorLength) {
				if ((fragY.equals(MapFragment.EMPTY) || fragY.equals(MapFragment.DEAD_END_Y))
						&& (fragNY.equals(MapFragment.EMPTY) || fragNY.equals(MapFragment.DEAD_END_NY))) {
					possibilities.add(MapFragment.CORRIDOR_X);
				}
			}
		}
	}

	private void checkDirectionsYNY(int corridorLength, int corridorSegmentCount, ArrayList<Map.MapFragment> possibilities) {
		if (fragX.equals(MapFragment.EMPTY)) {
			if (corridorSegmentCount >= corridorLength) {
				if (fragY.equals(MapFragment.EMPTY) && fragNY.equals(MapFragment.EMPTY)) {
					if (fragNXY.equals(MapFragment.EMPTY) && fragNXNY.equals(MapFragment.EMPTY)) {
						if (fragXY.equals(MapFragment.EMPTY) && fragXNY.equals(MapFragment.EMPTY)) {
							possibilities.add(MapFragment.CROSSING);
						} else if ((fragXY.equals(MapFragment.EMPTY) || fragXY.equals(MapFragment.DEAD_END_X))
								&& (fragXNY.equals(MapFragment.EMPTY) || fragXNY.equals(MapFragment.DEAD_END_X))) {
							possibilities.add(MapFragment.T_CROSSING_NX);
						}
					}
				}
			}
		}
	}

	private void checkDirectionNY(int corridorLength, int corridorSegmentCount, ArrayList<Map.MapFragment> possibilities) {
		if (fragX.equals(MapFragment.EMPTY)) {
			if (fragNY.equals(MapFragment.EMPTY)) {
				if (fragNXNY.equals(MapFragment.EMPTY)) {
					if (fragXNY.equals(MapFragment.EMPTY)) {
						if (corridorSegmentCount >= corridorLength) {
							possibilities.add(MapFragment.T_CROSSING_NY);
						} else {
							possibilities.add(MapFragment.CURVE_NX_NY);
						}
					} else if (fragXY.equals(MapFragment.DEAD_END_X)) {
						possibilities.add(MapFragment.CURVE_NX_NY);
					}
				}
			}
		}
	}

	private void checkDirectionY(int corridorLength, int corridorSegmentCount, ArrayList<Map.MapFragment> possibilities) {
		if (fragX.equals(MapFragment.EMPTY)) {
			if (fragY.equals(MapFragment.EMPTY)) {
				if (fragNXY.equals(MapFragment.EMPTY)) {
					if (fragXY.equals(MapFragment.EMPTY)) {
						if (corridorSegmentCount >= corridorLength) {
							possibilities.add(MapFragment.T_CROSSING_Y);
						} else {
							possibilities.add(MapFragment.CURVE_NX_Y);
						}
					} else if (fragXY.equals(MapFragment.DEAD_END_X)) {
						possibilities.add(MapFragment.CURVE_NX_Y);
					}
				}
			}
		}
	}

	@Override
	public int[] getPreviousCoordinates() {
		int[] previousCoordinates = { (creationIndexX - 1), creationIndexY, creationIndexZ };
		return previousCoordinates;
	}
}
